import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Checkbox, Select, Empty, Tooltip } from 'antd';
import { get, uniq, difference } from 'lodash';
import cn from 'classnames';
import { List as VList, AutoSizer } from 'react-virtualized';
import './index.less';

const SelectOption = Select.Option;

class CheckboxSelect extends Component {
  constructor(props) {
    super(props);
    const { optionKey = '_id', options = [], defaultSelected, selected } = props;
    this.state = {
      selectedKeys: defaultSelected || selected || [],
      allKeys: options.map(option => get(option, optionKey)),
      search: ''
    };
  }

  // eslint-disable-next-line
  UNSAFE_componentWillReceiveProps(props) {
    const { selected } = props;
    if (Array.isArray(selected)) {
      this.setState({
        selectedKeys: selected
      });
    }
  }

  setSelectedOptions = keys => {
    this.setState({ selectedKeys: keys }, () => {
      const onChange = this.props.onChange;
      if (typeof onChange === 'function') {
        onChange(this.state.selectedKeys);
      }
    });
  };

  onDeselect = value => {
    const { selectedKeys } = this.state;
    let newKeys = selectedKeys.filter(key => key !== value);
    this.setSelectedOptions(newKeys);
  };

  onCheckAll = e => {
    const { options: originOptions, optionKey = '_id', namePath = 'name' } = this.props;
    const { selectedKeys, search } = this.state;
    const searchRe = new RegExp(search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
    const allKeys = originOptions
      .filter(option => searchRe.test(get(option, namePath, '-')))
      .map(optioin => get(optioin, optionKey));
    const checked = e.target.checked;
    const keys = checked ? uniq(selectedKeys.concat(allKeys)) : difference(selectedKeys, allKeys);
    this.setSelectedOptions(keys);
  };

  onCheckOne = (value, checked) => {
    const { selectedKeys } = this.state;
    const newKeys = checked
      ? uniq(selectedKeys.concat(value))
      : selectedKeys.filter(key => key !== value);
    this.setSelectedOptions(newKeys);
  };

  onSearch = search => {
    this.setState({ search });
  };

  render() {
    const {
      placeholder,
      options: originOptions,
      optionKey = '_id',
      namePath = 'name',
      className,
      allButton = true,
      boxHeight = 0
    } = this.props;

    const { selectedKeys, search } = this.state;
    const searchRe = new RegExp(search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
    const options = originOptions.filter(option => searchRe.test(get(option, namePath, '-')));
    const allKeys = options.map(optioin => get(optioin, optionKey));
    const checkedAll = selectedKeys.length && difference(allKeys, selectedKeys).length === 0;

    const renderItem = ({ index, key, style }) => {
      let option = options[index];
      let value = get(option, optionKey);
      return (
        <Checkbox
          style={style}
          value={value}
          key={key}
          checked={selectedKeys.includes(value)}
          onChange={e => this.onCheckOne(value, e.target.checked)}
        >
          <Tooltip title={get(option, namePath, '-')} placement="bottom">
            {get(option, namePath, '-')}
          </Tooltip>
        </Checkbox>
      );
    };

    return (
      <div className={cn('c-checkboxs-selecter', className)}>
        <Select
          className="selecter"
          mode="multiple"
          defaultActiveFirstOption={false}
          placeholder={placeholder}
          value={selectedKeys}
          // change的同时设置值会让复选框变为true，再次点击就会false，逻辑错误
          // onChange={this.setSelectedOptions}
          onDeselect={this.onDeselect}
          dropdownClassName="selecter__dropdown"
          optionFilterProp="children"
          maxTagTextLength={9}
          maxTagCount={5}
          open={false}
          showSearch={true}
          onSearch={this.onSearch}
          autoClearSearchValue={false}
        >
          {originOptions.map(option => (
            <SelectOption key={get(option, optionKey)}>{get(option, namePath, '-')}</SelectOption>
          ))}
        </Select>

        <div className="checker" style={boxHeight ? { height: boxHeight } : null}>
          {options.length ? (
            <AutoSizer>
              {({ width, height }) => (
                <VList
                  width={width}
                  height={height}
                  className="checker_vlist"
                  overscanRowCount={10}
                  rowCount={options.length}
                  rowHeight={20}
                  rowRenderer={renderItem}
                />
              )}
            </AutoSizer>
          ) : (
            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
          )}
        </div>
        <div className="check-all">
          {allButton && (
            <Checkbox checked={checkedAll} onChange={this.onCheckAll}>
              全部
            </Checkbox>
          )}
          <span>已选择{selectedKeys.length}项</span>
        </div>
      </div>
    );
  }
}

CheckboxSelect.propTypes = {
  placeholder: PropTypes.string,
  options: PropTypes.array,
  defaultSelected: PropTypes.array,
  selected: PropTypes.array,
  optionKey: PropTypes.string,
  namePath: PropTypes.string,
  onChange: PropTypes.func,
  className: PropTypes.string,
  allButton: PropTypes.bool,
  boxHeight: PropTypes.number
};

export default CheckboxSelect;
